[CI Visibility] Implement ITR code coverage backfill#8626
Conversation
BenchmarksBenchmark execution time: 2026-06-17 09:47:34 Comparing candidate commit e561524 in PR branch Found 0 performance improvements and 1 performance regressions! Performance is the same for 71 metrics, 0 unstable metrics, 62 known flaky benchmarks, 64 flaky benchmarks without significant changes.
|
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8626) and master. ✅ No regressions detected - check the details below Full Metrics ComparisonFakeDbCommand
HttpMessageHandler
Comparison explanationExecution-time benchmarks measure the whole time it takes to execute a program, and are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are highlighted in **red**. The following thresholds were used for comparing the execution times:
Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard. Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph). Duration chartsFakeDbCommand (.NET Framework 4.8)gantt
title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8626) - mean (75ms) : 72, 79
master - mean (73ms) : 71, 76
section Bailout
This PR (8626) - mean (79ms) : 76, 82
master - mean (78ms) : 75, 81
section CallTarget+Inlining+NGEN
This PR (8626) - mean (1,100ms) : 1051, 1148
master - mean (1,101ms) : 1056, 1147
FakeDbCommand (.NET Core 3.1)gantt
title Execution time (ms) FakeDbCommand (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8626) - mean (117ms) : 112, 121
master - mean (114ms) : 111, 118
section Bailout
This PR (8626) - mean (116ms) : 112, 119
master - mean (116ms) : 113, 119
section CallTarget+Inlining+NGEN
This PR (8626) - mean (796ms) : 771, 820
master - mean (794ms) : 771, 817
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8626) - mean (102ms) : 98, 106
master - mean (101ms) : 98, 105
section Bailout
This PR (8626) - mean (102ms) : 100, 105
master - mean (105ms) : 101, 109
section CallTarget+Inlining+NGEN
This PR (8626) - mean (957ms) : 917, 997
master - mean (948ms) : 910, 985
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8626) - mean (102ms) : 98, 107
master - mean (100ms) : 96, 103
section Bailout
This PR (8626) - mean (101ms) : 98, 104
master - mean (101ms) : 99, 103
section CallTarget+Inlining+NGEN
This PR (8626) - mean (824ms) : 782, 867
master - mean (826ms) : 779, 873
HttpMessageHandler (.NET Framework 4.8)gantt
title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8626) - mean (200ms) : 195, 205
master - mean (199ms) : 193, 206
section Bailout
This PR (8626) - mean (203ms) : 200, 207
master - mean (203ms) : 199, 207
section CallTarget+Inlining+NGEN
This PR (8626) - mean (1,200ms) : 1157, 1242
master - mean (1,194ms) : 1155, 1233
HttpMessageHandler (.NET Core 3.1)gantt
title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8626) - mean (286ms) : 281, 292
master - mean (284ms) : 277, 292
section Bailout
This PR (8626) - mean (289ms) : 281, 297
master - mean (285ms) : 277, 293
section CallTarget+Inlining+NGEN
This PR (8626) - mean (962ms) : 940, 984
master - mean (958ms) : 938, 977
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8626) - mean (279ms) : 271, 287
master - mean (278ms) : 272, 284
section Bailout
This PR (8626) - mean (279ms) : 274, 284
master - mean (277ms) : 269, 285
section CallTarget+Inlining+NGEN
This PR (8626) - mean (1,162ms) : 1128, 1195
master - mean (1,157ms) : 1118, 1196
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8626) - mean (279ms) : 272, 286
master - mean (276ms) : 270, 282
section Bailout
This PR (8626) - mean (279ms) : 273, 284
master - mean (277ms) : 272, 282
section CallTarget+Inlining+NGEN
This PR (8626) - mean (1,038ms) : 994, 1081
master - mean (1,035ms) : 994, 1077
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
7cf4fee to
c30b95f
Compare
77ebf83 to
b2c8a72
Compare
This comment has been minimized.
This comment has been minimized.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 59affa6b18
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
andrewlock
left a comment
There was a problem hiding this comment.
I got about 10% of the way through, but it's just too much, I literally couldn't keep the scope in my head 😅 :blind-approval:
I'd suggest a couple of rounds of AI review instead, because it's probably going to be more useful than me
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 51b6c71d39
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1497c386b3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
58670de to
0cc6d25
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0cc6d25d7f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
0cc6d25 to
2233166
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 22331664eb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
2233166 to
1ada8e0
Compare
|
@codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
1ada8e0 to
3b8c367
Compare
andrewlock
left a comment
There was a problem hiding this comment.
Not a chance 🙈 :blindfold:
Summary of changes
meta.coveragebitmaps from skippable-tests responses using the .NETFileBitmaprepresentation and persists scoped backfill data across child processes, injected sessions, AppDomains, and coverage tool adapters.test.code_coverage.lines_pctresult through source arbitration, withtest.code_coverage.backfilledwhen the selected result used backend-aware coverage data._missing_line_code_coverage=true. Missing or invalid aggregatemeta.coveragedisables safe backfill publication, but does not globally disable ITR skipping.customconfigurations.Reason for change
ITR can skip tests that would otherwise contribute line coverage. Without backfill, coverage tools and the Datadog session metric can under-report line coverage for a run where skipped tests were intentionally omitted. The backend now returns skipped-test line coverage in the skippable-tests response, so the tracer can merge backend line bitmaps with local coverage before publishing the session result or rewriting external reports.
References:
Java compatibility notes
This PR follows the Java reference behavior for the user-visible ITR decision:
customtest configurations are sent to the backend, but are not used for local post-filtering.test.bundle/module scope is used to associate backend candidates with the current module scope._missing_line_code_coverage=trueprevents skipping that candidate when line coverage is active.meta.coveragedoes not prevent ITR from skipping tests. It only means the .NET tracer must avoid publishing a backfilled coverage result that cannot be proven safe.The intentional implementation difference is bitmap representation: Java decodes backend coverage into
BitSet, while .NET keeps the existingFileBitmaprepresentation for both decoding backend coverage and sending/persisting coverage data.Review diagrams
End-to-end backfill flow
flowchart TD A["dotnet test / vstest / coverage command starts"] B["CoverageBackfillCapability inspects command, runsettings, response files, and report outputs"] C{"Line-capable coverage source active?"} D["Legacy ITR behavior; no backfill required"] E["Request scoped skippable tests for the current test.bundle/module"] F["Backend returns skippable candidates, _missing_line_code_coverage flags, and optional meta.coverage"] G["Java-compatible skip gate decides whether each candidate may be skipped"] H["Framework integration records the actual ITR skip only after it commits to skipping"] I["CoverageBackfillData decodes meta.coverage with FileBitmap"] J["CoverageBackfillDataStore persists backend coverage, actual-skip state, scoped backfillable state, IPC results, and IPC failures"] K["Coverage producers apply or rewrite line coverage results"] L["Validation checks paths, represented backend lines, producer completeness, and IPC state"] M["CodeCoverageResultAggregator selects one publishable source by priority"] N["Session publishes test.code_coverage.lines_pct and test.code_coverage.backfilled when applicable"] A --> B --> C C -- "no" --> D C -- "yes" --> E --> F F --> G --> H --> J F --> I --> J J --> K --> L --> M --> NSkippable scope and Java-compatible skip gate
flowchart TD A["Skippable-tests response item"] B{"Top-level test.bundle mismatches scoped request?"} C["Drop only this mismatched candidate"] D["Keep candidate; do not filter by custom configs"] E{"Line coverage active?"} F["Use legacy ITR skip behavior"] G{"Candidate has _missing_line_code_coverage=true?"} H["Do not skip this candidate"] I["Allow ITR skip"] J["meta.coverage is decoded separately and is not part of the skip decision"] A --> B B -- "yes" --> C B -- "no" --> D D --> E E -- "no" --> F --> I E -- "yes" --> G G -- "yes" --> H G -- "no or absent" --> I J -. "matches Java" .-> GCoverage producers, persistence, and publication
flowchart LR A["Backend meta.coverage FileBitmap data"] B["Actual ITR skip markers"] C["CoverageBackfillDataStore"] subgraph Producers["Coverage producers"] D["Datadog internal coverage"] E["Coverlet in-memory result"] F["Coverlet collector XML fallback"] G["Cobertura/OpenCover XML"] H["Microsoft CodeCoverage XML"] end I["Apply backend line bitmaps or rewrite customer-visible XML"] J["Send live IPC result or persist result/failure marker"] K["Validate source paths, represented lines, partial merges, and IPC completeness"] L["Suppress stale or unsafe results"] M["Select highest-priority publishable source"] N["Publish final session coverage tags"] A --> C B --> C C --> Producers Producers --> I --> J --> K K -- "safe" --> M --> N K -- "unsafe" --> LImplementation details
CoverageBackfillDataparsing for backendmeta.coverage, including bitmap decoding, validation, merging, and source-path normalization.CoverageBackfillDataStoreto persist backend coverage, actual-skip markers, backfillable scoped skip state, coverage IPC results, and coverage IPC failures across process and AppDomain boundaries.test.bundleplus runtime/configuration fingerprinting so backend coverage matches the current local execution scope.Test.Closerecords the session-level "ITR skip happened" tag state later._missing_line_code_coverageflag, while aggregate backend coverage validity is tracked separately for deciding whether a backfilled coverage result can be published.CoverageBackfillCapabilityand command-line parsing for activation checks acrossdotnet test,vstest,dotnet-coverage, Coverlet collector/MSBuild, Microsoft CodeCoverage, response files, runsettings, MSBuild properties, filters, framework selectors, thresholds, and generated report paths.CodeCoverageResultAggregatorto select the final session result by source priority and suppress ambiguous count-based same-source merges.Key behavior cases
meta.coverageis missing or invalid, ITR can still skip tests, but the session will not publish a backfilled coverage result unless another validated producer result is available.Source priority
CodeCoverageResultAggregatorselects the highest-priority publishable result:ExternalXmlCoverletXmlFallbackCoverletMicrosoftCodeCoverageUnknownDatadogInternalSame-source results with line counts are only publishable when they were explicitly merged by the producer or can be validated without ambiguous count aggregation.
Type guide
CoverageBackfillDatameta.coveragebitmaps.CoverageBackfillDataStoreCoverageBackfillCapabilityCoverageBackfillCommandLineCoverageBackfillPathMatcher/CoverageBackfillPathMatchTrackerCoverageBackfillApplicatorExternalCoverageXmlBackfillCoverletCoverageBackfillCodeCoverageBackfillValidationTestOptimizationSkippableFeatureSessionCodeCoverageMessageCodeCoverageResultAggregatorTest coverage
Added and expanded coverage across:
meta.coverageparsing, bitmap merging, invalid payload handling, missing coverage, and missing-line metadata;customconfigurations andtest.bundlemodule scope;LineCallCountsemantics;dotnet test, VSTest, Coverlet, Microsoft CodeCoverage,dotnet-coverage, response file, runsettings, and MSBuild command detection;Recent validation:
net10.0.AttributeTests.AttributesInstantiationsOnlyUseBuiltinTypespassed onnet10.0andnet9.0x64.IpcTests.IpcClientCanSendCoverageMessageWithBackfillValidationpassed onnet10.0.ManagedVanguardStopIntegrationTests.DeduplicatesEquivalentMicrosoftLineXmlPathsBeforeBackfillpassed onnet10.0.git diff --check: clean.